home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Plug-In Power Pack for Netscape Communicator
/
Plug-In Power Pack for Netscape Communicator.iso
/
plugins
/
dataviews
/
dvtools
/
demos
/
telecomdemo
/
do_simul.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-10
|
15KB
|
555 lines
#ifndef lint
static char SccsId[]= "@(#)do_simul.c V1.13 5/2/95";
#endif
/*
| File name: do_simul.c
|========================================================================
|
| Copyright (c) 1990 -- V.I. Corporation
|
|========================================================================
*/
#include "std.h"
#include "simulate.h"
#include "tlc_fundecl.h"
/***************** Begin Function Declarations *************/
LOCAL void ClearPartStatus V_P_((char *part_name, PART_STRUCT *part_struct, ADDRESS args));
LOCAL void ClearNodeStatus V_P_((char *node_name, NODE_STRUCT *node_struct, ADDRESS args));
LOCAL void ClearLinkStatus V_P_((char *link_name, LINK_STRUCT *link_struct, ADDRESS args));
LOCAL void ForceError V_P_((void));
LOCAL void UpdateParts V_P_((char *part_name, PART_STRUCT *part_struct, ADDRESS args));
LOCAL void RecordError V_P_((PART_STRUCT *part_struct));
LOCAL void UpdateLinks V_P_((char *link_name, LINK_STRUCT *link_struct, ADDRESS args));
LOCAL void UpdateNodes V_P_((VIEW_STRUCT *view_struct));
LOCAL int ComputeNodeStatus V_P_((NODE_STRUCT *node_struct));
LOCAL int RandomError V_P_((char *part_name));
LOCAL int GetParentNodeStatus V_P_((PART_STRUCT *part_struct));
/***************** End Function Declarations *************/
/*
* StartSimulation -- start the simulation. Reset the iteration number,
* set the status of ll network components to normal, and draw the
* top level view.
*/
void StartSimulation
V_P_ ((void))
{
SimParams.iter_number = 1;
VTsttraverse (SimParams.switch_tab, (VTSTTRAVERSEFUNPTR) ClearPartStatus,
(ADDRESS) NULL);
VTsttraverse (SimParams.part_tab, (VTSTTRAVERSEFUNPTR) ClearPartStatus,
(ADDRESS) NULL);
VTsttraverse (SimParams.node_tab, (VTSTTRAVERSEFUNPTR) ClearNodeStatus,
(ADDRESS) NULL);
VTsttraverse (SimParams.link_tab, (VTSTTRAVERSEFUNPTR) ClearLinkStatus,
(ADDRESS) NULL);
if (SimParams.curr_view)
NewMainView (SimParams.curr_view, SimParams.top_view);
else
NewMainView ((VIEW_STRUCT *) NULL, SimParams.top_view);
}
/*
* ClearPartStatus -- used by traversal routine to set the status
* of a part to normal.
*/
/* ARGSUSED */
LOCAL void
ClearPartStatus (part_name, part_struct, args)
char *part_name;
PART_STRUCT *part_struct;
ADDRESS args;
{
part_struct->status = NORMAL;
}
/*
* ClearNodeStatus -- called by traversal routine to return the
* status of all nodes to normal, and to clear the error counters.
*/
/* ARGSUSED */
LOCAL void
ClearNodeStatus (node_name, node_struct, args)
char *node_name;
NODE_STRUCT *node_struct;
ADDRESS args;
{
node_struct->status = NORMAL;
node_struct->failure_count = 0;
node_struct->critical_count = 0;
node_struct->softerror_count = 0;
}
/*
* ClearLinkStatus -- called by traversal routine to change the status
* of links to normal.
*/
/* ARGSUSED */
LOCAL void
ClearLinkStatus (link_name, link_struct, args)
char *link_name;
LINK_STRUCT *link_struct;
ADDRESS args;
{
link_struct->status = NORMAL;
}
/*
* NextSimulationStep -- perform the next step in the simulation. Check
* for a restart, check for a forced error, and update the status of all
* network components.
*/
void NextSimulationStep
V_P_ ((void))
{
/*
* If the restart flag has been set, then reset the subviews, restart
* the simulation, and clear the restart flag.
*/
if (*Control.restart_flag)
{
ResetSubviews ();
StartSimulation ();
*Control.restart_flag = 0;
return;
}
/*
* Update the interation number, force an error if the flag is set.
* Otherwise, update the status of the parts and switches, and then
* update the status of the nodes and links.
*/
SimParams.iter_number++;
if (*Control.force_error_flag)
{
ForceError ();
*Control.force_error_flag = 0;
}
else
{
VTsttraverse (SimParams.switch_tab, (VTSTTRAVERSEFUNPTR) UpdateParts,
(ADDRESS) NULL);
VTsttraverse (SimParams.part_tab, (VTSTTRAVERSEFUNPTR) UpdateParts,
(ADDRESS) NULL);
}
VTsttraverse (SimParams.link_tab, (VTSTTRAVERSEFUNPTR) UpdateLinks,
(ADDRESS) NULL);
UpdateNodes (SimParams.top_view);
}
/*
* ForceError -- force an error in one of the switches. Pick one
* of the switches at random and change its status to failure.
*/
LOCAL void ForceError
V_P_ ((void))
{
INT switchno, num_switches;
PART_STRUCT *part_struct;
SYMNODE symnode;
num_switches = VTstlen (SimParams.switch_tab);
switchno = (INT) (num_switches * VUfrand ());
symnode = VTstsnget (SimParams.switch_tab, switchno);
part_struct = (PART_STRUCT *) VTsnvalue (symnode);
part_struct->status = FULL_FAILURE;
RecordError (part_struct);
}
/*
* UpdateParts -- change the status of all parts and switches.
* If the part is already broken, then check to see if the part
* needs to be fixed automatically. Otherwise, use a random
* function to get a new part status.
*/
/* ARGSUSED */
LOCAL void
UpdateParts (part_name, part_struct, args)
char *part_name;
PART_STRUCT *part_struct;
ADDRESS args;
{
if (part_struct->status == MAJOR_CRITICAL ||
part_struct->status == FULL_FAILURE)
{
/*
* If enough time has passed since the part has broken then it
* should be autofixed. Or, if the part has been scheduled to
* be fixed, then check to see if that time has arrived.
*/
if ((part_struct->error_time + (INT) (*Control.autofix_delay)) <
SimParams.iter_number)
{
part_struct->status = NORMAL;
OutputInfo ((INT) SimParams.iter_number, FIX_DONE,
part_struct->part_name, "Otto");
}
else if (part_struct->fix_time == SimParams.iter_number)
{
part_struct->status = NORMAL;
OutputInfo ((INT) SimParams.iter_number, FIX_DONE,
part_struct->part_name, (CHAR *) NULL);
}
}
else
{
part_struct->status = RandomError (part_struct->part_name);
RecordError (part_struct);
}
}
/*
* RecordError -- check the status of the part and update the correct
* counter in the parent node.
*/
LOCAL void
RecordError (part_struct)
PART_STRUCT *part_struct;
{
NODE_STRUCT *node_struct;
node_struct = part_struct->primary_node;
switch (part_struct->status)
{
case SOFT_ERROR:
part_struct->status = NORMAL;
node_struct->softerror_count++;
OutputInfo ((INT) SimParams.iter_number, SOFT,
part_struct->part_name, (CHAR *) NULL);
break;
case MAJOR_CRITICAL:
node_struct->critical_count++;
part_struct->error_time = SimParams.iter_number;
OutputInfo ((INT) SimParams.iter_number, CRITICAL,
part_struct->part_name, (CHAR *) NULL);
break;
case FULL_FAILURE:
node_struct->failure_count++;
part_struct->error_time = SimParams.iter_number;
OutputInfo ((INT) SimParams.iter_number, FULL_FAIL,
part_struct->part_name, (CHAR *) NULL);
break;
default:
break;
}
}
#define ERROR_POS 8
#define WHERE_POS 28
#define WHAT_POS 45
#define WHO_POS 55
void
OutputInfo (iter_num, type, part_name, ident)
int iter_num;
int type;
char *part_name;
char *ident;
{
INT i;
CHAR msg[255];
CHAR *name;
CHAR *ptr, *next_tok;
CHAR *what, *where;
VIEW_STRUCT *view_struct;
NODE_STRUCT *node_struct;
msg[0] = 0;
name = StrClone (part_name);
get_token (name, &ptr, &next_tok);
#ifdef WINNT
(VOID)sprintf( msg, "%5d", iter_num );
#else /*Not WINNT */
(VOID) sprintf (msg, "%d\t", iter_num);
#endif /* WINNT */
for (i = strlen (msg); i < ERROR_POS; i++)
msg[i] = ' ';
if (strncmp (ptr, "switch", 6) == 0)
{
what = "switch";
where = next_tok;
}
else
{
view_struct = GetNamedView (ptr);
node_struct = view_struct->back_ptr;
where = node_struct->node_name;
what = next_tok;
}
switch (type)
{
case SOFT:
(VOID) sprintf (&msg[ERROR_POS], "SOFT ERROR");
break;
case CRITICAL:
(VOID) sprintf (&msg[ERROR_POS], "CRITICAL ERROR");
break;
case FULL_FAIL:
(VOID) sprintf (&msg[ERROR_POS], "FULL FAILURE");
break;
case FIX_ORDER:
(VOID) sprintf (&msg[ERROR_POS], "FIX ORDER");
break;
case FIX_DONE:
(VOID) sprintf (&msg[ERROR_POS], "FIX COMPLETED");
break;
}
for (i = strlen (msg); i < WHERE_POS; i++)
msg[i] = ' ';
(VOID) sprintf (&msg[WHERE_POS], "%s", where);
for (i = strlen (msg); i < WHAT_POS; i++)
msg[i] = ' ';
(VOID) sprintf (&msg[WHAT_POS], "%s", what);
for (i = strlen (msg); i < WHO_POS; i++)
msg[i] = ' ';
if (ident)
(VOID) sprintf (&msg[WHO_POS], "By: %s", ident);
else
msg[WHO_POS] = '\0';
OutputLog (msg);
S_FREE (name);
}
/*
* UpdateLinks -- update the status of a link based on its switches.
* If either or both of a link's switches exist, then compute the link's
* status based on the status of the switches.
*/
/* ARGSUSED */
LOCAL void
UpdateLinks (link_name, link_struct, args)
char *link_name;
LINK_STRUCT *link_struct;
ADDRESS args;
{
PART_STRUCT *switch1, *switch2;
SHORT status;
status = NORMAL;
switch1 = link_struct->switch1;
switch2 = link_struct->switch2;
if (switch1)
status |= switch1->status;
if (switch2)
status |= switch2->status;
link_struct->status = status;
}
/*
* UpdateNodes -- update the status of all nodes in a view. Traverse
* the list of nodes in a view, computing new statuses for each.
*/
LOCAL void
UpdateNodes (view_struct)
VIEW_STRUCT *view_struct;
{
NODE_STRUCT *node_struct;
node_struct = view_struct->node_list;
while (node_struct != NULL)
{
node_struct->status |= ComputeNodeStatus (node_struct);
node_struct = node_struct->next;
}
}
/*
* ComputeNodeStatus -- compute the status of a node. If the node has
* subnodes, then compute the status of this node based on the status
* of all of its subnodes. If the node has no subnodes, compute its
* status based on the status of its parts.
*/
LOCAL int
ComputeNodeStatus (node_struct)
NODE_STRUCT *node_struct;
{
VIEW_STRUCT *view_struct;
PART_STRUCT *part_ptr;
NODE_STRUCT *sec_node_struct;
SHORT status;
/*
* If the node has no subview, then keep its status as normal.
*/
view_struct = node_struct->view_ptr;
if (view_struct == NULL)
return NORMAL;
/*
* If the node has no subnodes, then figure the status of the node
* from its component parts.
*/
if (view_struct->node_list == NULL)
{
part_ptr = view_struct->part_list;
node_struct->status = NORMAL;
while (part_ptr != NULL)
{
node_struct->status |= GetParentNodeStatus (part_ptr);
part_ptr = part_ptr->next;
}
return node_struct->status;
}
else
{
/*
* If the node has subnodes, then compute the node status
* based on the composite status of the subnodes and the
* severity of the error.
*/
sec_node_struct = view_struct->node_list;
status = NORMAL;
while (sec_node_struct != NULL)
{
status |= ComputeNodeStatus (sec_node_struct);
sec_node_struct = sec_node_struct->next;
}
if (status & FULL_FAILURE)
node_struct->status = MAJOR_CRITICAL;
else if (status & MAJOR_CRITICAL)
node_struct->status = MAJOR_CRITICAL;
else if (status & MINOR_CRITICAL)
node_struct->status = MINOR_WARNING;
else if (status & MAJOR_WARNING)
node_struct->status = MAJOR_WARNING;
else
node_struct->status = NORMAL;
}
return node_struct->status;
}
/*
* Define error frequency based on number of errors per 30 iterations.
*/
#define NUM_FAILURES 3
#define NUM_CRITICALS 6
#define NUM_SOFTERRORS 21
#define TOT_ERRORS 30
/*
* RandomError -- compute an status based on random values. Compute
* the new status based on the error frequencies, the error factor
* set by the user, and a random value.
*/
/* ARGSUSED */
LOCAL int
RandomError (part_name)
char *part_name;
{
INT chances, range;
FLOAT setpoint, result;
chances = SimParams.total_parts * 100;
range = (chances * 2) - (chances / 2);
setpoint = (FLOAT)((chances / 2) +
(range * ((100.0 - *Control.error_factor) / 100.0)));
result = (FLOAT)(setpoint * VUfrand ());
if (result < TOT_ERRORS)
{
if (result < NUM_FAILURES)
return FULL_FAILURE;
if (result < (NUM_FAILURES + NUM_CRITICALS))
return MAJOR_CRITICAL;
else
return SOFT_ERROR;
}
else
return NORMAL;
}
/*
* GetParentNodeStatus -- compute the status of the parent node based on
* the status of the part and the inheritence properties of the part.
*/
LOCAL int
GetParentNodeStatus (part_struct)
PART_STRUCT *part_struct;
{
SHORT status;
/*
* If the part status is normal or one of the warning values, then
* the node assumes the same status.
*/
status = part_struct->status;
if (status == (SHORT) NORMAL)
return (SHORT) NORMAL;
else if (status == (SHORT) MAJOR_WARNING)
return (SHORT) MAJOR_WARNING;
else if (status == (SHORT) MINOR_WARNING)
return (SHORT) MINOR_WARNING;
/*
* If the status is major critical then return the status of the
* parent node based on the values in the inheritence string.
*/
else if (status == (SHORT) MAJOR_CRITICAL)
switch (part_struct->err_prop[1])
{
case 'c':
if (part_struct->err_prop[2] == '+')
return (SHORT) MAJOR_CRITICAL;
else
return (SHORT) MINOR_CRITICAL;
break;
case 'w':
if (part_struct->err_prop[2] == '+')
return (SHORT) MAJOR_WARNING;
else
return (SHORT) MINOR_WARNING;
break;
default:
return (SHORT) NORMAL;
}
/*
* If the status is full failure then return the status of the
* parent node based on the values in the inheritence string.
*/
else if (status == (SHORT) FULL_FAILURE)
switch (part_struct->err_prop[0])
{
case 'f':
return (SHORT) FULL_FAILURE;
break;
case 'c':
if (part_struct->err_prop[2] == '+')
return (SHORT) MAJOR_CRITICAL;
else
return (SHORT) MINOR_CRITICAL;
break;
case 'w':
if (part_struct->err_prop[2] == '+')
return (SHORT) MAJOR_WARNING;
else
return (SHORT) MINOR_WARNING;
break;
default:
return (SHORT) NORMAL;
}
return (SHORT) NORMAL;
}